1111import static java .util .Arrays .asList ;
1212import static org .apache .logging .log4j .LogManager .getLogger ;
1313
14+ import java .io .ByteArrayInputStream ;
15+ import java .io .ByteArrayOutputStream ;
1416import java .io .IOException ;
1517import java .io .OutputStream ;
1618import java .util .Enumeration ;
1719import java .util .HashMap ;
1820import java .util .List ;
1921import java .util .Map ;
2022import javax .xml .stream .XMLStreamException ;
23+ import javax .xml .transform .Result ;
24+ import javax .xml .transform .Source ;
25+ import javax .xml .transform .Transformer ;
26+ import javax .xml .transform .TransformerException ;
27+ import javax .xml .transform .TransformerFactory ;
28+ import javax .xml .transform .stream .StreamResult ;
29+ import javax .xml .transform .stream .StreamSource ;
2130
2231import com .lyncode .xoai .dataprovider .OAIDataProvider ;
2332import com .lyncode .xoai .dataprovider .OAIRequestParameters ;
2433import com .lyncode .xoai .dataprovider .core .XOAIManager ;
2534import com .lyncode .xoai .dataprovider .exceptions .InvalidContextException ;
2635import com .lyncode .xoai .dataprovider .exceptions .OAIException ;
2736import com .lyncode .xoai .dataprovider .exceptions .WritingXmlException ;
37+ import jakarta .annotation .PostConstruct ;
2838import jakarta .servlet .ServletException ;
2939import jakarta .servlet .http .HttpServletRequest ;
3040import jakarta .servlet .http .HttpServletResponse ;
3141import org .apache .logging .log4j .Logger ;
3242import org .dspace .core .Context ;
43+ import org .dspace .services .ConfigurationService ;
3344import org .dspace .xoai .services .api .cache .XOAICacheService ;
3445import org .dspace .xoai .services .api .config .XOAIManagerResolver ;
3546import org .dspace .xoai .services .api .config .XOAIManagerResolverException ;
4152import org .dspace .xoai .services .impl .xoai .DSpaceResumptionTokenFormatter ;
4253import org .springframework .beans .factory .annotation .Autowired ;
4354import org .springframework .boot .autoconfigure .condition .ConditionalOnProperty ;
55+ import org .springframework .core .io .DefaultResourceLoader ;
56+ import org .springframework .core .io .Resource ;
57+ import org .springframework .core .io .ResourceLoader ;
58+ import org .springframework .http .MediaType ;
4459import org .springframework .stereotype .Controller ;
4560import org .springframework .ui .Model ;
4661import org .springframework .web .bind .annotation .PathVariable ;
5772public class DSpaceOAIDataProvider {
5873 private static final Logger log = getLogger (DSpaceOAIDataProvider .class );
5974
75+ private TransformerFactory htmlTransformerFactory = null ;
76+ private byte [] htmlTransformerSource = null ;
77+
6078 @ Autowired
6179 XOAICacheService cacheService ;
6280 @ Autowired
@@ -69,9 +87,32 @@ public class DSpaceOAIDataProvider {
6987 IdentifyResolver identifyResolver ;
7088 @ Autowired
7189 SetRepositoryResolver setRepositoryResolver ;
90+ @ Autowired
91+ ConfigurationService configurationService ;
7292
7393 private DSpaceResumptionTokenFormatter resumptionTokenFormat = new DSpaceResumptionTokenFormatter ();
7494
95+ @ PostConstruct
96+ public void setUpHTMLTransformerFactory () {
97+ try {
98+ XOAIManager manager = xoaiManagerResolver .getManager ();
99+ if (configurationService .getBooleanProperty ("oai.html" , true ) && manager .hasStyleSheet ()) {
100+ ResourceLoader resourceLoader = new DefaultResourceLoader ();
101+ String styleSheetPath = manager .getStyleSheet ();
102+ Resource styleSheetResource = resourceLoader .getResource ("classpath:" + styleSheetPath );
103+ htmlTransformerSource = styleSheetResource .getContentAsByteArray ();
104+ htmlTransformerFactory = TransformerFactory .newInstance ();
105+ // run for potential exceptions only as a sanity check on the XSLT:
106+ htmlTransformerFactory .newTransformer (
107+ new StreamSource (new ByteArrayInputStream (htmlTransformerSource )));
108+ }
109+ } catch (Exception e ) {
110+ htmlTransformerFactory = null ;
111+ htmlTransformerSource = null ;
112+ log .warn ("Could not set up HTML transformer for OAI-PMH app: " + e .toString ());
113+ }
114+ }
115+
75116 @ RequestMapping ("" )
76117 public void index (HttpServletResponse response , HttpServletRequest request ) throws IOException {
77118 response .sendRedirect (request .getRequestURI () + "/" );
@@ -92,7 +133,8 @@ public String indexAction(HttpServletResponse response, Model model) throws Serv
92133
93134 @ RequestMapping ("/{context}" )
94135 public String contextAction (Model model , HttpServletRequest request , HttpServletResponse response ,
95- @ PathVariable ("context" ) String xoaiContext ) throws IOException , ServletException {
136+ @ PathVariable ("context" ) String xoaiContext )
137+ throws IOException , ServletException , TransformerException {
96138 Context context = null ;
97139 try {
98140 request .setCharacterEncoding ("UTF-8" );
@@ -109,7 +151,26 @@ public String contextAction(Model model, HttpServletRequest request, HttpServlet
109151 OutputStream out = response .getOutputStream ();
110152 OAIRequestParameters parameters = new OAIRequestParameters (buildParametersMap (request ));
111153
112- response .setContentType ("text/xml" );
154+ boolean shouldServeAsHTML = false ;
155+ List <MediaType > acceptMediaTypes = MediaType .parseMediaTypes (request .getHeader ("Accept" ));
156+ if (htmlTransformerFactory != null ) {
157+ response .addHeader ("Vary" , "Accept" );
158+ for (MediaType acceptMediaType : acceptMediaTypes ) {
159+ if (acceptMediaType .includes (MediaType .TEXT_XML ) ||
160+ acceptMediaType .includes (MediaType .APPLICATION_XML )) {
161+ break ;
162+ } else if (acceptMediaType .includes (MediaType .TEXT_HTML )) {
163+ shouldServeAsHTML = true ;
164+ }
165+ }
166+ }
167+
168+ if (shouldServeAsHTML ) {
169+ response .setContentType ("text/html" );
170+ out = new ByteArrayOutputStream ();
171+ } else {
172+ response .setContentType ("text/xml" );
173+ }
113174 response .setCharacterEncoding ("UTF-8" );
114175
115176 String identification = xoaiContext + parameters .requestID ();
@@ -124,6 +185,15 @@ public String contextAction(Model model, HttpServletRequest request, HttpServlet
124185 dataProvider .handle (parameters , out );
125186 }
126187
188+ if (shouldServeAsHTML ) {
189+ OutputStream responseOut = response .getOutputStream ();
190+ Source source = new StreamSource (new ByteArrayInputStream (((ByteArrayOutputStream ) out ).toByteArray ()));
191+ Result result = new StreamResult (responseOut );
192+ Transformer htmlTransformer = htmlTransformerFactory .newTransformer (
193+ new StreamSource (new ByteArrayInputStream (htmlTransformerSource )));
194+ htmlTransformer .transform (source , result );
195+ out = responseOut ;
196+ }
127197
128198 out .flush ();
129199 out .close ();
0 commit comments