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     }
00095     
00096     SynchroFileGeneratorManager.getManager(); 
00097   }
00098 
00099   public void run(HttpServletRequest request, HttpServletResponse res) throws ServletException, IOException  {
00100     // validate client
00101     User user = null;
00102     String group = request.getParameter("openMISGroup");
00103     if (group == null)  {
00104       LogManager.traceError(0, "OpenMSPService bad request no openMISGroup parameter.");
00105       res.setStatus(HttpServletResponse.SC_FORBIDDEN);
00106       return;
00107     }
00108 
00109     try {
00110       // get cyberML message
00111       String openMSPString = request.getParameter("openMISData");
00112       try {
00113         openMSPString = new String(uncompressAndDecodeRequest(openMSPString.getBytes()));
00114       } catch (Throwable ex)  {
00115         // not encoded or compressed data.
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       // validate user auth.
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       // log new synchro
00156       LogManager.traceUserSynchro(LogServices.SYNCHROSERVICE, request.getRemoteAddr()+"#"+user.getId()+"#"+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         String version = null;
00232         this.callService(cred, serviceName, message, answer, terminal, version, profil, fileSystem);
00233       } else if (element.getElementType() == Element.STATUS)  {// not supported
00234         Status status = new  Status (((Status)element).getCmdId(), Status.STATUS_COMMAND_NOT_IMPLEMENTED) ;
00235         answer.add(status);
00236       } else if ((element.getElementType() == Element.SYNC)
00237           || (element.getElementType() == Element.MAP)
00238           || (element.getElementType() == Element.GET)
00239             ){
00240         String serviceName = ((Command)element).getTarget();
00241         String version = null;
00242         this.callService(cred, serviceName, message, answer, terminal, version, profil, fileSystem);
00243       } else if (element.getElementType() == Element.SEQUENCE) {
00244         while (message.hasMoreMessage())  {
00245           ContainerMessage commandContainer = message.nextMessage();
00246           this.dispatchElement(cred, group, commandContainer, answer, terminal, profil, fileSystem);
00247         }
00248       } else if (element.getElementType() == Element.FINAL) {
00249       } else  {
00250         Status status = new  Status (((RequestCommand)element).getCmdId(), Status.STATUS_WRONG_FORMAT) ;
00251         answer.add(status);
00252       }
00253     } catch (Exception ex)  {
00254       try {
00255         LogManager.trace(new SynchroException(ex));
00256         Status status = new  Status (((RequestCommand)element).getCmdId(), Status.STATUS_FAILED) ;
00257         answer.add(status);
00258       } catch (Exception e)  {
00259         LogManager.trace(new SynchroException(e));
00260       }
00261     }
00262   }
00263 
00264   private final void callService(Credential cred, String serviceName, ContainerMessage message, Message answer, UserTerminal terminal, String version,  Profile profil, FileSystem  fileSystem) throws OpenMSPException {
00265     try {
00266       ProxySyncroTarget proxy = SynchroTargerManager.getManager().getProxySynchroTargetForTerminal(terminal);
00267       if (proxy != null)  {
00268         proxy.executeOpenMSPCommande(cred, serviceName, message, answer, terminal, version, profil, fileSystem);
00269       } else  {
00270         Status status = new  Status (((AbstractCommand)message.getElement()).getCmdId(), Status.STATUS_NOT_FOUND) ;
00271         answer.add(status);
00272         LogManager.traceInfo(LogServices.SYNCHROSERVICE, "Service "+serviceName+" ask by CyberML commande and not available");
00273       }
00274     } catch (Throwable e)  {
00275       LogManager.trace(new SynchroException(e));
00276       Status status = new  Status (((AbstractCommand)message.getElement()).getCmdId(), Status.STATUS_FAILED) ;
00277       answer.add(status);
00278     }
00279   }
00280 
00281   public String getServiceUri() {
00282     return ServiceManager.getManager().getServiceBaseURI()+"/openmspservice";
00283   }
00284 
00285   public byte[] uncompressAndDecodeRequest(byte[] request) throws IOException {
00286     // decode compressed data
00287     byte[] decodedData = GeneralCoder.decodeBase64(request);
00288 
00289     // uncompresse data
00290     ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
00291     ByteArrayInputStream inStream = new ByteArrayInputStream(decodedData);
00292     GZIPInputStream zipStream = new GZIPInputStream(inStream);
00293     try {
00294       byte[] buff = new byte[1024];
00295       int length;
00296       while ((length = zipStream.read(buff)) != -1) {
00297         byteStream.write(buff, 0, length);
00298       }
00299     } finally  {
00300       zipStream.close();
00301       byteStream.close();
00302     }
00303     return byteStream.toByteArray();
00304   }
00305 }

Generated on Mon Jan 14 17:29:49 2008 for OpenMobileIS by  doxygen 1.5.4