00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 package org.openmobileis.synchro.openmsp.server;
00030
00031
00032 import org.openmobileis.common.user.User;
00033 import org.openmobileis.common.user.UserManager;
00034 import org.openmobileis.common.user.UserNotFoundException;
00035 import org.openmobileis.common.user.profile.Profile;
00036 import org.openmobileis.common.user.profile.ProfileDataManager;
00037 import org.openmobileis.common.user.profile.ProfileNotFoundException;
00038 import org.openmobileis.common.util.PropertiesManager;
00039 import org.openmobileis.common.util.codec.GeneralCoder;
00040 import org.openmobileis.common.context.*;
00041 import org.openmobileis.common.util.exception.*;
00042 import org.openmobileis.common.util.log.*;
00043 import org.openmobileis.services.Service;
00044 import org.openmobileis.services.common.ServiceManager;
00045 import org.openmobileis.synchro.openmsp.OpenMSPException;
00046 import org.openmobileis.synchro.openmsp.client.core.OpenMSPSyncMessageFactory;
00047 import org.openmobileis.synchro.openmsp.protocol.AbstractCommand;
00048 import org.openmobileis.synchro.openmsp.protocol.Command;
00049 import org.openmobileis.synchro.openmsp.protocol.ContainerMessage;
00050 import org.openmobileis.synchro.openmsp.protocol.Element;
00051 import org.openmobileis.synchro.openmsp.protocol.Header;
00052 import org.openmobileis.synchro.openmsp.protocol.Message;
00053 import org.openmobileis.synchro.openmsp.protocol.MessageFactory;
00054 import org.openmobileis.synchro.openmsp.protocol.RequestCommand;
00055 import org.openmobileis.synchro.openmsp.protocol.Result;
00056 import org.openmobileis.synchro.openmsp.protocol.Status;
00057 import org.openmobileis.synchro.openmsp.server.synctarget.SynchroTargerManager;
00058 import org.openmobileis.synchro.openmsp.server.synctarget.proxy.ProxySyncroTarget;
00059 import org.openmobileis.synchro.openmsp.server.util.FileSystem;
00060 import org.openmobileis.synchro.openmsp.server.util.FileSystemObjectPool;
00061 import org.openmobileis.synchro.openmsp.server.util.FileSystemObjectPoolSelecter;
00062 import org.openmobileis.synchro.openmsp.server.util.MemoryFile;
00063 import org.openmobileis.synchro.openmsp.server.util.SynchroFileGenerator;
00064 import org.openmobileis.synchro.openmsp.server.util.SynchroFileGeneratorManager;
00065 import org.openmobileis.synchro.security.auth.Credential;
00066 import org.openmobileis.synchro.security.auth.CredentialCodec;
00067
00068 import java.io.IOException;
00069 import java.io.ByteArrayInputStream;
00070 import java.io.ByteArrayOutputStream;
00071 import java.util.zip.*;
00072
00073 import javax.servlet.ServletException;
00074 import javax.servlet.http.HttpServletRequest;
00075 import javax.servlet.http.HttpServletResponse;
00076
00084 public class OpenMSPService extends Service{
00085
00086 public OpenMSPService() {
00087 String synchrologfile = PropertiesManager.getManager().getProperty("org.openmobileis.synchro.openmsp.server.log.filename");
00088 if (synchrologfile != null) {
00089 java.util.Properties props = new java.util.Properties();
00090 props.put("LOGFILE", synchrologfile);
00091 OpenMSPServiceTracer tracer = new OpenMSPServiceTracer();
00092 tracer.setLogTracerProperties(props);
00093 LogManager.attachLogTracerToPriority(LogPriorities.USERSYNCHRO, tracer);
00094 }
00095 }
00096
00097 public void run(HttpServletRequest request, HttpServletResponse res) throws ServletException, IOException {
00098
00099 User user = null;
00100 String group = request.getParameter("openMISGroup");
00101 if (group == null) {
00102 LogManager.traceError(0, "OpenMSPService bad request no openMISGroup parameter.");
00103 res.setStatus(HttpServletResponse.SC_FORBIDDEN);
00104 return;
00105 }
00106
00107
00108
00109 try {
00110
00111 String openMSPString = request.getParameter("openMISData");
00112 try {
00113 openMSPString = new String(uncompressAndDecodeRequest(openMSPString.getBytes()));
00114 } catch (Throwable ex) {
00115
00116 LogManager.traceError(0, ex);
00117 res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
00118 return;
00119 }
00120
00121
00122 Message openMLMessage = MessageFactory.getFactory().getMessage(openMSPString);
00123
00124 Header header = openMLMessage.getHeader();
00125
00126
00127 String[] credential = header.getCredential();
00128 Credential cred = null;
00129 if (credential != null) {
00130 cred = CredentialCodec.getOpenMSPCredential(credential);
00131 String userId = UserManager.getManager().authenticateUser(group, cred.getPrincipal(), cred.getPassword());
00132 user = UserManager.getManager().getUser(group,userId);
00133 } else {
00134 LogManager.traceError(0, "OpenMSPService no credential in OpenMSP request.");
00135 res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
00136 return;
00137 }
00138 Profile profil = ProfileDataManager.getManager().getProfil(group, user.getProfil());
00139 SessionContext context = SessionContextManager.getManager().getSessionContext();
00140 UserTerminal terminal = (UserTerminal)context.getTerminal();
00141 if (terminal == null) {
00142 String useragent = UserTerminal.getUserAgentFromRequest(request);
00143 terminal = new UserTerminal(useragent);
00144 context.setTerminal(terminal);
00145 }
00146
00147 if (!terminal.isOPenMISClient()) {
00148 LogManager.traceError(0, "Synchro terminal is not supported for user:"+user.getLogin());
00149 res.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
00150 return;
00151 }
00152 context.setUserId(user.getId());
00153 context.setUserGroup(group);
00154
00155
00156 LogManager.traceUserSynchro(LogServices.SYNCHROSERVICE, request.getRemoteAddr()+"#"+user.getId()+"#"+group+"#"+terminal.getClientPlateformType()+"#"+terminal.getSynchroType());
00157
00158 long sessionNumber = header.getSessionID();
00159
00160
00161
00162
00163
00164
00165
00166 String target = header.getTarget();
00167 String source = header.getSource();
00168 if (target.indexOf(OpenMSPSyncMessageFactory.OpenMSPTARGET) == -1) {
00169 res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
00170 }
00171
00172
00173 FileSystemObjectPool pool = FileSystemObjectPoolSelecter.getPool(terminal);
00174 FileSystem fileSystem = pool.getFileSystem();
00175
00176 try {
00177
00178
00179
00180 Message CMLAnswer = MessageFactory.getFactory().createMessage(new Header(sessionNumber+1, target, source , null, null));
00181
00182 openMLMessage.resetCursor();
00183
00184 while (openMLMessage.hasMoreMessage()) {
00185 ContainerMessage CMLRequest = openMLMessage.nextMessage();
00186 this.dispatchElement(cred, group, CMLRequest, CMLAnswer, terminal, profil, fileSystem);
00187 }
00188
00189
00190
00191
00192 ByteArrayInputStream input = new ByteArrayInputStream(CMLAnswer.encode().getBytes());
00193 fileSystem.addFile(new MemoryFile("/cyberML.xml", input));
00194
00195 SynchroFileGenerator fileGenerator = SynchroFileGeneratorManager.getManager().getFileGenerator(terminal);
00196 fileGenerator.generateSynchroFile(terminal, profil, request, res, fileSystem, Long.toString(sessionNumber+1));
00197
00198 res.setStatus(HttpServletResponse.SC_OK);
00199 } finally {
00200 pool.disposeObject(fileSystem);
00201 }
00202 } catch (OpenMSPException ex) {
00203 res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
00204 LogManager.trace(new SynchroException(ex));
00205 } catch (UserNotFoundException ex) {
00206 res.setStatus(HttpServletResponse.SC_FORBIDDEN);
00207 } catch(ProfileNotFoundException ex) {
00208 LogManager.traceError(0, "OpenMSPService no Profil for user login :"+user.getLogin());
00209 res.setStatus(HttpServletResponse.SC_FORBIDDEN);
00210 } catch (Throwable ex) {
00211 res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
00212 LogManager.trace(new SynchroException(ex));
00213 } finally {
00214 if (user != null) {
00215 try {
00216 UserManager.getManager().logoutUser(group, user.getId());
00217 } catch (ServiceException ex) {
00218 LogManager.trace(ex);
00219
00220 }
00221 }
00222 }
00223 }
00224
00225 private final void dispatchElement(Credential cred, String group, ContainerMessage message, Message answer, UserTerminal terminal, Profile profil, FileSystem fileSystem) {
00226 Element element = message.getElement();
00227 try {
00228 if (element.getElementType() == Element.RESULT) {
00229 String serviceName = ((Result)element).getSourceRef();
00230 String version = null;
00231 this.callService(cred, serviceName, message, answer, terminal, version, profil, fileSystem);
00232 } else if (element.getElementType() == Element.STATUS) {
00233 Status status = new Status (((Status)element).getCmdId(), Status.STATUS_COMMAND_NOT_IMPLEMENTED) ;
00234 answer.add(status);
00235 } else if ((element.getElementType() == Element.SYNC)
00236 || (element.getElementType() == Element.MAP)
00237 || (element.getElementType() == Element.GET)
00238 ){
00239 String serviceName = ((Command)element).getTarget();
00240 String version = null;
00241 this.callService(cred, serviceName, message, answer, terminal, version, profil, fileSystem);
00242 } else if (element.getElementType() == Element.SEQUENCE) {
00243 while (message.hasMoreMessage()) {
00244 ContainerMessage commandContainer = message.nextMessage();
00245 this.dispatchElement(cred, group, commandContainer, answer, terminal, profil, fileSystem);
00246 }
00247 } else if (element.getElementType() == Element.FINAL) {
00248 } else {
00249 Status status = new Status (((RequestCommand)element).getCmdId(), Status.STATUS_WRONG_FORMAT) ;
00250 answer.add(status);
00251 }
00252 } catch (Exception ex) {
00253 try {
00254 LogManager.trace(new SynchroException(ex));
00255 Status status = new Status (((RequestCommand)element).getCmdId(), Status.STATUS_FAILED) ;
00256 answer.add(status);
00257 } catch (Exception e) {
00258 LogManager.trace(new SynchroException(e));
00259 }
00260 }
00261 }
00262
00263 private final void callService(Credential cred, String serviceName, ContainerMessage message, Message answer, UserTerminal terminal, String version, Profile profil, FileSystem fileSystem) throws OpenMSPException {
00264 try {
00265 ProxySyncroTarget proxy = SynchroTargerManager.getManager().getProxySynchroTargetForTerminal(terminal);
00266 if (proxy != null) {
00267 proxy.executeOpenMSPCommande(cred, serviceName, message, answer, terminal, version, profil, fileSystem);
00268 } else {
00269 Status status = new Status (((AbstractCommand)message.getElement()).getCmdId(), Status.STATUS_NOT_FOUND) ;
00270 answer.add(status);
00271 LogManager.traceInfo(LogServices.SYNCHROSERVICE, "Service "+serviceName+" ask by CyberML commande and not available");
00272 }
00273 } catch (Throwable e) {
00274 LogManager.trace(new SynchroException(e));
00275 Status status = new Status (((AbstractCommand)message.getElement()).getCmdId(), Status.STATUS_FAILED) ;
00276 answer.add(status);
00277 }
00278 }
00279
00280 public String getServiceUri() {
00281 return ServiceManager.getManager().getServiceBaseURI()+"/openmspservice";
00282 }
00283
00284 public byte[] uncompressAndDecodeRequest(byte[] request) throws IOException {
00285
00286 byte[] decodedData = GeneralCoder.decodeBase64(request);
00287
00288
00289 ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
00290 ByteArrayInputStream inStream = new ByteArrayInputStream(decodedData);
00291 GZIPInputStream zipStream = new GZIPInputStream(inStream);
00292 try {
00293 byte[] buff = new byte[1024];
00294 int length;
00295 while ((length = zipStream.read(buff)) != -1) {
00296 byteStream.write(buff, 0, length);
00297 }
00298 } finally {
00299 zipStream.close();
00300 byteStream.close();
00301 }
00302 return byteStream.toByteArray();
00303 }
00304 }