001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/context/control/ContextSaveListener.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    
037    package org.deegree.portal.standard.context.control;
038    
039    import java.io.File;
040    import java.io.FileOutputStream;
041    import java.io.OutputStream;
042    
043    import javax.servlet.http.HttpServletRequest;
044    import javax.servlet.http.HttpSession;
045    import javax.xml.transform.Source;
046    import javax.xml.transform.Transformer;
047    import javax.xml.transform.TransformerFactory;
048    import javax.xml.transform.dom.DOMSource;
049    import javax.xml.transform.stream.StreamResult;
050    
051    import org.deegree.enterprise.control.FormEvent;
052    import org.deegree.enterprise.control.RPCMember;
053    import org.deegree.enterprise.control.RPCMethodCall;
054    import org.deegree.enterprise.control.RPCParameter;
055    import org.deegree.enterprise.control.RPCStruct;
056    import org.deegree.enterprise.control.RPCUtils;
057    import org.deegree.enterprise.control.RPCWebEvent;
058    import org.deegree.framework.log.ILogger;
059    import org.deegree.framework.log.LoggerFactory;
060    import org.deegree.framework.util.StringTools;
061    import org.deegree.framework.xml.XMLFragment;
062    import org.deegree.i18n.Messages;
063    import org.deegree.model.spatialschema.Envelope;
064    import org.deegree.portal.Constants;
065    import org.deegree.portal.PortalException;
066    import org.deegree.portal.context.ViewContext;
067    import org.deegree.portal.context.XMLFactory;
068    import org.w3c.dom.Document;
069    
070    /**
071     * This class saves a new context based on changes made by the user (on the client) and based on the
072     * original context xml. <br/> Files are saved under .../WEB-INF/xml/users/some_user, where
073     * some_user is passed as an RPC parameter. Files should be saved with .xml extension because the
074     * default load context listener class looks up those files. <br/>
075     *
076     * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
077     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
078     * @author last edited by: $Author: mschneider $
079     *
080     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
081     */
082    public class ContextSaveListener extends AbstractContextListener {
083    
084        private static final ILogger LOG = LoggerFactory.getLogger( ContextSaveListener.class );
085    
086        private static String userDir = "WEB-INF/conf/igeoportal/users/";
087    
088        private static String contextDir = "WEB-INF/conf/igeoportal/";
089    
090        /*
091         * (non-Javadoc)
092         *
093         * @see org.deegree.enterprise.control.WebListener#actionPerformed(org.deegree.enterprise.control.FormEvent)
094         */
095        @Override
096        public void actionPerformed( FormEvent event ) {
097    
098            RPCWebEvent rpc = (RPCWebEvent) event;
099            try {
100                validate( rpc );
101            } catch ( PortalException e ) {
102                LOG.logError( e.getMessage(), e );
103                gotoErrorPage( Messages.getMessage( "IGEO_STD_CNTXT_INVALID_RPC", "ContextSave", e.getMessage() ) );
104                return;
105            }
106    
107            String newContext = null;
108            try {
109                newContext = storeContext( rpc );
110            } catch ( Exception e ) {
111                LOG.logError( e.getMessage(), e );
112                gotoErrorPage( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_SAVE_CNTXT" ) );
113                return;
114            }
115    
116            // forward to new page
117            this.getRequest().setAttribute( Constants.MESSAGE,
118                                            Messages.getMessage( "IGEO_STD_CNTXT_SUCCESS_SAVE_CNTXT", newContext ) );
119        }
120    
121        /**
122         * stores the current context of the user with a defined name
123         *
124         * @param event
125         * @return name of the context that has been stored
126         * @throws PortalException
127         */
128        private String storeContext( RPCWebEvent event )
129                                throws PortalException {
130    
131            RPCMethodCall mc = event.getRPCMethodCall();
132            RPCParameter[] pars = mc.getParameters();
133            RPCStruct struct = (RPCStruct) pars[0].getValue();
134    
135            // read base context
136            StringBuffer path2Dir = new StringBuffer( getHomePath() );
137            path2Dir.append( contextDir );
138    
139            // access base context
140            HttpSession session = ( (HttpServletRequest) getRequest() ).getSession();
141            ViewContext vc = (ViewContext) session.getAttribute( Constants.CURRENTMAPCONTEXT );
142            // change values: BBOX and Layer List
143            Envelope bbox = extractBBox( (RPCStruct) struct.getMember( Constants.RPC_BBOX ).getValue(), null );
144            changeBBox( vc, bbox );
145            RPCMember[] layerList = ( (RPCStruct) struct.getMember( "layerList" ).getValue() ).getMembers();
146            changeLayerList( vc, layerList );
147    
148            // save new context
149            // get map context value
150            String username = "default";
151            try {
152                String sid = RPCUtils.getRpcPropertyAsString( struct, "sessionID" );
153                LOG.logDebug( "sessionID ", sid );
154                username = getUserName( sid );
155                if ( username == null ) {
156                    username = "default";
157                }
158                LOG.logDebug( "username ", username );
159            } catch ( Exception e ) {
160                LOG.logError( e.getMessage(), e );
161            }
162    
163            String newContext = RPCUtils.getRpcPropertyAsString( struct, "newContext" );
164            path2Dir = new StringBuffer( getHomePath() );
165            path2Dir.append( userDir );
166            path2Dir.append( username );
167            File file = new File( path2Dir.toString() );
168            if ( !file.exists() ) {
169                // create directory if not exists
170                file.mkdir();
171            }
172            path2Dir.append( "/" );
173            path2Dir.append( newContext );
174    
175            saveDocument( vc, path2Dir.toString() );
176    
177            return newContext;
178        }
179    
180        /**
181         * saves the new context as xml
182         *
183         * @param vc
184         * @param filename
185         * @throws PortalException
186         */
187        public static final void saveDocument( ViewContext vc, String filename )
188                                throws PortalException {
189            try {
190                XMLFragment xml = XMLFactory.export( vc );
191                FileOutputStream fos = new FileOutputStream( filename );
192                xml.write( fos );
193                fos.close();
194            } catch ( Exception e ) {
195                LOG.logError( e.getMessage(), e );
196                throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_SAVE_FILE", filename ) );
197            }
198        }
199    
200        /**
201         * validates the incoming RPC event
202         *
203         * @param rpc
204         * @throws PortalException
205         */
206        private void validate( RPCWebEvent rpc )
207                                throws PortalException {
208            RPCMethodCall mc = rpc.getRPCMethodCall();
209            RPCParameter param = mc.getParameters()[0];
210            RPCStruct struct = (RPCStruct) param.getValue();
211            RPCMember username = struct.getMember( "sessionID" );
212            if ( username == null ) {
213                throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_MISSING_PARAM", "sessionID", "ContextSave" ) );
214            }
215            RPCMember newContext = struct.getMember( "newContext" );
216            if ( newContext == null ) {
217                throw new PortalException(
218                                           Messages.getMessage( "IGEO_STD_CNTXT_MISSING_PARAM", "newContext", "ContextSave" ) );
219            }
220            RPCMember layerList = struct.getMember( "layerList" );
221            if ( layerList == null ) {
222                throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_MISSING_PARAM", "layerList", "ContextSave" ) );
223            }
224            // TODO validate box: should do this in a common (static) method
225            // for many listeners that need a bbox
226        }
227    
228        /**
229         * common method to save xml
230         *
231         * @param os
232         * @param doc
233         * @throws PortalException
234         */
235        protected static void internalSave( OutputStream os, Document doc )
236                                throws PortalException {
237            try {
238                Source source = new DOMSource( doc );
239                Transformer transformer = TransformerFactory.newInstance().newTransformer();
240                transformer.transform( source, new StreamResult( os ) );
241            } catch ( Exception e ) {
242                throw new PortalException( Messages.getMessage( "IGEO_STD_CNTXT_ERROR_INTERNAL_SAVE",
243                                                                StringTools.stackTraceToString( e.getStackTrace() ) ) );
244            }
245        }
246    
247    }