OpenMSPService.java

00001 /*
00002  * OpenMobileIS - a free Java(TM) Framework for mobile applications Java(TM)
00003  * Copyright (C) 2004-2006 Philippe Delrieu
00004  * All rights reserved.
00005  * Contact: pdelrieu@openmobileis.org
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00020  * USA
00021  *
00022  *  Author : Philippe Delrieu
00023  *
00024  *  Modifications :
00025  *  2004 Creation P.Delrieu
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       LogManager.traceInfo(0, "Log synchro access in :"+synchrologfile);
00095     }
00096     
00097     SynchroFileGeneratorManager.getManager(); 
00098   }
00099 
00100   public void run(HttpServletRequest request, HttpServletResponse res) throws ServletException, IOException  {
00101     // validate client
00102     User user = null;
00103     String group = request.getParameter("openMISGroup");
00104     if (group == null)  {
00105       LogManager.traceError(0, "OpenMSPService bad request no openMISGroup parameter.");
00106       res.setStatus(HttpServletResponse.SC_FORBIDDEN);
00107       return;
00108     }
00109 
00110     try {
00111       // get cyberML message
00112       String openMSPString = request.getParameter("openMISData");
00113       try {
00114         openMSPString = new String(uncompressAndDecodeRequest(openMSPString.getBytes()));
00115       } catch (Throwable ex)  {
00116         // not encoded or compressed data.
00117         LogManager.traceError(0, ex);
00118         res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
00119         return;
00120       }
00121 
00122 
00123       Message openMLMessage =  MessageFactory.getFactory().getMessage(openMSPString);
00124 
00125       Header header = openMLMessage.getHeader();
00126 
00127       // validate user auth.
00128       String[] credential = header.getCredential();
00129       Credential cred = null;
00130       if (credential != null) {
00131         cred = CredentialCodec.getOpenMSPCredential(credential);
00132         String userId = UserManager.getManager().authenticateUser(group, cred.getPrincipal(), cred.getPassword());
00133         user = UserManager.getManager().getUser(group,userId);
00134       } else  {
00135         LogManager.traceError(0, "OpenMSPService no credential in OpenMSP request.");
00136         res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
00137         return;
00138       }
00139       Profile profil = ProfileDataManager.getManager().getProfil(group, user.getProfil());
00140       SessionContext context = SessionContextManager.getManager().getSessionContext();
00141       String useragent = UserTerminal.getUserAgentFromRequest(request);
00142       UserTerminal terminal = new UserTerminal(useragent);
00143       context.setTerminal(terminal);
00144       
00145       LogManager.traceDebug(0, "OpenMSPService user profile :"+profil.profilName);
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       // log new synchro
00156       LogManager.traceUserSynchro(LogServices.SYNCHROSERVICE, request.getRemoteAddr()+"#"+user.getId()+"#"+user.getLogin()+"#"+group+"#"+terminal.getClientPlateformType()+"#"+terminal.getSynchroType());
00157 
00158       long sessionNumber = header.getSessionID();
00159  /*     SynchroNumber currentSynchroNumber = null;
00160       try {
00161         currentSynchroNumber = SyncNumberManager.getManager().getSynchroNumber(sessionNumber);
00162       } catch (SyncNumberNotFoundException ex) {
00163         LogManager.trace(ex);
00164         currentSynchroNumber = new SynchroNumber(0,0);
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       // init client file management
00173       FileSystemObjectPool pool = FileSystemObjectPoolSelecter.getPool(terminal);
00174       FileSystem  fileSystem = pool.getFileSystem();
00175 
00176       try {
00177 //        SynchroNumber newSynchroNumber = SyncNumberManager.getManager().getNextSynchroNumber();
00178 
00179         // create answer message
00180         Message CMLAnswer = MessageFactory.getFactory().createMessage(new Header(sessionNumber+1, target, source , null, null));
00181 
00182         openMLMessage.resetCursor();
00183         // dispatcher commande ( Get | Map | Results | Sequence | Status | Sync)+, Final?)
00184         while (openMLMessage.hasMoreMessage()) {
00185           ContainerMessage CMLRequest = openMLMessage.nextMessage();
00186           this.dispatchElement(cred, group, CMLRequest, CMLAnswer, terminal, profil, fileSystem);
00187         }
00188 
00189         // end SyncML code management
00190 
00191         // save CyberML file
00192         ByteArrayInputStream input = new ByteArrayInputStream(CMLAnswer.encode().getBytes());
00193         fileSystem.addFile(new MemoryFile("/cyberML.xml", input));
00194         //generate synchro file
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         if (ex.getSyncStatus() != OpenMSPException.NO_STATUS_DEFINED) res.setStatus(ex.getSyncStatus());
00204         else res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
00205       LogManager.trace(new SynchroException(ex));
00206     } catch (UserNotFoundException ex) {
00207       res.setStatus(HttpServletResponse.SC_FORBIDDEN);
00208     } catch(ProfileNotFoundException ex)  {
00209       LogManager.traceError(0, "OpenMSPService no Profil for user login :"+user.getLogin());
00210       res.setStatus(HttpServletResponse.SC_FORBIDDEN);
00211     } catch (Throwable ex) {
00212       res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
00213       LogManager.trace(new SynchroException(ex));
00214     } finally   {
00215         if (user != null)       {
00216                 try     {
00217                         UserManager.getManager().logoutUser(group, user.getId());
00218                 } catch (ServiceException ex)   {
00219           LogManager.trace(ex);
00220 
00221                 }
00222         }
00223     }
00224   }
00225 
00226   private final void dispatchElement(Credential cred, String group, ContainerMessage message, Message answer, UserTerminal terminal, Profile profil, FileSystem  fileSystem) {
00227     Element element = message.getElement();
00228     try {
00229       if (element.getElementType() == Element.RESULT)  {
00230         String serviceName = ((Result)element).getSourceRef();
00231         this.callService(cred, serviceName, message, answer, terminal, profil, fileSystem);
00232       } else if (element.getElementType() == Element.STATUS)  {// not supported
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         this.callService(cred, serviceName, message, answer, terminal, profil, fileSystem);
00241       } else if (element.getElementType() == Element.SEQUENCE) {
00242         while (message.hasMoreMessage())  {
00243           ContainerMessage commandContainer = message.nextMessage();
00244           this.dispatchElement(cred, group, commandContainer, answer, terminal, profil, fileSystem);
00245         }
00246       } else if (element.getElementType() == Element.FINAL) {
00247       } else  {
00248         Status status = new  Status (((RequestCommand)element).getCmdId(), Status.STATUS_WRONG_FORMAT) ;
00249         answer.add(status);
00250       }
00251     } catch (Exception ex)  {
00252       try {
00253         LogManager.trace(new SynchroException(ex));
00254         Status status = new  Status (((RequestCommand)element).getCmdId(), Status.STATUS_FAILED) ;
00255         answer.add(status);
00256       } catch (Exception e)  {
00257         LogManager.trace(new SynchroException(e));
00258       }
00259     }
00260   }
00261 
00262   private final void callService(Credential cred, String serviceName, ContainerMessage message, Message answer, UserTerminal terminal, Profile profil, FileSystem  fileSystem) throws OpenMSPException {
00263     try {
00264       ProxySyncroTarget proxy = SynchroTargerManager.getManager().getProxySynchroTargetForTerminal(terminal);
00265       if (proxy != null)  {
00266         proxy.executeOpenMSPCommande(cred, serviceName, message, answer, terminal, profil, fileSystem);
00267       } else  {
00268         Status status = new  Status (((AbstractCommand)message.getElement()).getCmdId(), Status.STATUS_NOT_FOUND) ;
00269         answer.add(status);
00270         LogManager.traceInfo(LogServices.SYNCHROSERVICE, "Service "+serviceName+" ask by CyberML commande and not available");
00271       }
00272     } catch (Throwable e)  {
00273       LogManager.trace(new SynchroException(e));
00274       Status status = new  Status (((AbstractCommand)message.getElement()).getCmdId(), Status.STATUS_FAILED) ;
00275       answer.add(status);
00276     }
00277   }
00278 
00279   public String getServiceUri() {
00280     return ServiceManager.getManager().getServiceBaseURI()+"/openmspservice";
00281   }
00282 
00283   public byte[] uncompressAndDecodeRequest(byte[] request) throws IOException {
00284     // decode compressed data
00285     byte[] decodedData = GeneralCoder.decodeBase64(request);
00286 
00287     // uncompresse data
00288     ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
00289     ByteArrayInputStream inStream = new ByteArrayInputStream(decodedData);
00290     GZIPInputStream zipStream = new GZIPInputStream(inStream);
00291     try {
00292       byte[] buff = new byte[1024];
00293       int length;
00294       while ((length = zipStream.read(buff)) != -1) {
00295         byteStream.write(buff, 0, length);
00296       }
00297     } finally  {
00298       zipStream.close();
00299       byteStream.close();
00300     }
00301     return byteStream.toByteArray();
00302   }
00303 }

Generated on Mon Jan 11 21:19:16 2010 for OpenMobileIS by  doxygen 1.5.4