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