View Javadoc
1   /*
2    * $Id$ $Revision:
3    * 20489 $ $Date$
4    * 
5    * This file is part of *** M y C o R e *** See http://www.mycore.de/ for
6    * details.
7    * 
8    * This program is free software; you can use it, redistribute it and / or
9    * modify it under the terms of the GNU General Public License (GPL) as
10   * published by the Free Software Foundation; either version 2 of the License or
11   * (at your option) any later version.
12   * 
13   * This program is distributed in the hope that it will be useful, but WITHOUT
14   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16   * details.
17   * 
18   * You should have received a copy of the GNU General Public License along with
19   * this program, in a file called gpl.txt or license.txt. If not, write to the
20   * Free Software Foundation Inc., 59 Temple Place - Suite 330, Boston, MA
21   * 02111-1307 USA
22   */
23  
24  package org.mycore.mets.servlets;
25  
26  import java.io.IOException;
27  import java.nio.file.Files;
28  import java.text.MessageFormat;
29  import java.util.Collection;
30  
31  import javax.servlet.ServletException;
32  import javax.servlet.http.HttpServletRequest;
33  import javax.servlet.http.HttpServletResponse;
34  
35  import org.apache.logging.log4j.LogManager;
36  import org.apache.logging.log4j.Logger;
37  import org.jdom2.Document;
38  import org.mycore.common.MCRSession;
39  import org.mycore.common.MCRSessionMgr;
40  import org.mycore.common.config.MCRConfiguration;
41  import org.mycore.common.content.MCRContent;
42  import org.mycore.common.content.MCRJDOMContent;
43  import org.mycore.common.content.MCRPathContent;
44  import org.mycore.common.xml.MCRLayoutService;
45  import org.mycore.datamodel.common.MCRLinkTableManager;
46  import org.mycore.datamodel.metadata.MCRDerivate;
47  import org.mycore.datamodel.metadata.MCRMetadataManager;
48  import org.mycore.datamodel.metadata.MCRObjectID;
49  import org.mycore.datamodel.niofs.MCRPath;
50  import org.mycore.frontend.MCRFrontendUtil;
51  import org.mycore.frontend.servlets.MCRServlet;
52  import org.mycore.frontend.servlets.MCRServletJob;
53  import org.mycore.mets.model.MCRMETSGeneratorFactory;
54  import org.mycore.mets.tools.MCRMetsSave;
55  
56  /**
57   * @author Thomas Scheffler (yagee)
58   */
59  public class MCRMETSServlet extends MCRServlet {
60  
61      private static final long serialVersionUID = 1L;
62  
63      private static final Logger LOGGER = LogManager.getLogger(MCRMETSServlet.class);
64  
65      public static final boolean STORE_METS_ON_GENERATE = MCRConfiguration.instance()
66          .getBoolean("MCR.Mets.storeMetsOnGenerate");
67  
68      private boolean useExpire;
69  
70      private static int CACHE_TIME;
71  
72      @Override
73      protected void doGetPost(MCRServletJob job) throws Exception {
74          HttpServletRequest request = job.getRequest();
75          HttpServletResponse response = job.getResponse();
76          LOGGER.info(request.getPathInfo());
77  
78          String derivate = getOwnerID(request.getPathInfo());
79          MCRPath rootPath = MCRPath.getPath(derivate, "/");
80  
81          if (!Files.isDirectory(rootPath)) {
82              response.sendError(HttpServletResponse.SC_NOT_FOUND,
83                  MessageFormat.format("Derivate {0} does not exist.", derivate));
84              return;
85          }
86          request.setAttribute("XSL.derivateID", derivate);
87          Collection<String> linkList = MCRLinkTableManager.instance().getSourceOf(derivate);
88          if (linkList.isEmpty()) {
89              MCRDerivate derivate2 = MCRMetadataManager.retrieveMCRDerivate(MCRObjectID.getInstance(derivate));
90              MCRObjectID ownerID = derivate2.getOwnerID();
91              if (ownerID != null && ownerID.toString().length() != 0) {
92                  linkList.add(ownerID.toString());
93              } else {
94                  response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
95                      MessageFormat.format(
96                          "Derivate {0} is not linked with a MCRObject. Please contact an administrator.", derivate));
97                  return;
98              }
99          }
100         request.setAttribute("XSL.objectID", linkList.iterator().next());
101         response.setContentType("text/xml");
102 
103         long lastModified = Files.getLastModifiedTime(rootPath).toMillis();
104 
105         MCRFrontendUtil.writeCacheHeaders(response, (long) CACHE_TIME, lastModified, useExpire);
106         long start = System.currentTimeMillis();
107         MCRContent metsContent = getMetsSource(job, useExistingMets(request), derivate);
108         MCRLayoutService.instance().doLayout(request, response, metsContent);
109         LOGGER.info("Generation of code by {} took {} ms", this.getClass().getSimpleName(),
110             System.currentTimeMillis() - start);
111     }
112 
113     /**
114      * Returns the mets document wrapped in a {@link MCRContent} object.
115      */
116     static MCRContent getMetsSource(MCRServletJob job, boolean useExistingMets, String derivate) throws Exception {
117         MCRPath metsPath = MCRPath.getPath(derivate, "/mets.xml");
118 
119         try {
120             job.getRequest().setAttribute("XSL.derivateID", derivate);
121             String objectid = MCRLinkTableManager.instance().getSourceOf(derivate).iterator().next();
122 
123             if (objectid == null || objectid.length() == 0) {
124                 MCRDerivate derObj = MCRMetadataManager.retrieveMCRDerivate(MCRObjectID.getInstance(derivate));
125                 MCRObjectID ownerID = derObj.getOwnerID();
126                 objectid = ownerID.toString();
127             }
128 
129             job.getRequest().setAttribute("XSL.objectID", objectid);
130         } catch (Exception x) {
131             LOGGER.warn("Unable to set \"XSL.objectID\" attribute to current request", x);
132         }
133 
134         boolean metsExists = Files.exists(metsPath);
135         if (metsExists && useExistingMets) {
136             MCRContent content = new MCRPathContent(metsPath);
137             content.setDocType("mets");
138             return content;
139         } else {
140             Document mets = MCRMETSGeneratorFactory.create(MCRPath.getPath(derivate, "/")).generate().asDocument();
141             if (!metsExists && STORE_METS_ON_GENERATE) {
142                 MCRMetsSave.saveMets(mets, MCRObjectID.getInstance(derivate));
143             }
144             return new MCRJDOMContent(mets);
145         }
146     }
147 
148     /*
149      * (non-Javadoc)
150      * 
151      * @see org.mycore.frontend.servlets.MCRServlet#init()
152      */
153     @Override
154     public void init() throws ServletException {
155         super.init();
156         String cacheParam = getInitParameter("cacheTime");
157         /* default is one day */
158         CACHE_TIME = cacheParam != null ? Integer.parseInt(cacheParam) : (60 * 60 * 24);
159         useExpire = MCRConfiguration.instance().getBoolean("MCR.Component.MetsMods.Servlet.UseExpire", true);
160     }
161 
162     private boolean useExistingMets(HttpServletRequest request) {
163         String useExistingMetsParam = request.getParameter("useExistingMets");
164         if (useExistingMetsParam == null) {
165             return true;
166         }
167         return Boolean.valueOf(useExistingMetsParam);
168     }
169 
170     public static String getOwnerID(String pathInfo) {
171         StringBuilder ownerID = new StringBuilder(pathInfo.length());
172         boolean running = true;
173         for (int i = (pathInfo.charAt(0) == '/') ? 1 : 0; (i < pathInfo.length() && running); i++) {
174             switch (pathInfo.charAt(i)) {
175                 case '/':
176                     running = false;
177                     break;
178                 default:
179                     ownerID.append(pathInfo.charAt(i));
180                     break;
181             }
182         }
183         return ownerID.toString();
184     }
185 
186     /*
187      * (non-Javadoc)
188      * 
189      * @see
190      * org.mycore.frontend.servlets.MCRServlet#getLastModified(javax.servlet
191      * .http.HttpServletRequest)
192      */
193     @Override
194     protected long getLastModified(HttpServletRequest request) {
195         String ownerID = getOwnerID(request.getPathInfo());
196         MCRSessionMgr.unlock();
197         MCRSession session = MCRSessionMgr.getCurrentSession();
198         MCRPath metsPath = MCRPath.getPath(ownerID, "/mets.xml");
199         try {
200             session.beginTransaction();
201             try {
202                 if (Files.exists(metsPath)) {
203                     return Files.getLastModifiedTime(metsPath).toMillis();
204                 } else if (Files.isDirectory(metsPath.getParent())) {
205                     return Files.getLastModifiedTime(metsPath.getParent()).toMillis();
206                 }
207             } catch (IOException e) {
208                 LOGGER.warn("Error while retrieving last modified information from {}", metsPath, e);
209             }
210             return -1L;
211         } finally {
212             session.commitTransaction();
213             MCRSessionMgr.releaseCurrentSession();
214             session.close(); // just created session for db transaction
215             MCRSessionMgr.lock();
216         }
217     }
218 
219 }