/* * Copyright 2011 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.openehealth.ipf.labs.maven.confluence.export; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URL; import java.rmi.RemoteException; import java.util.List; import javax.xml.rpc.ServiceException; import org.apache.commons.io.IOUtils; import org.apache.http.HttpException; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.maven.plugin.logging.Log; /** * @author Mitko Kolev * */ public abstract class AbstractConfluenceExportTemplate { protected final URL confluenceBaseUrl; protected final String user; protected final String password; protected final Log log; public AbstractConfluenceExportTemplate(URL confluenceBaseUrl, String user, String password, Log log) { this.confluenceBaseUrl = confluenceBaseUrl; this.user = user; this.password = password; this.log = log; } public void export(DefaultHttpClient httpClient, List<ExportSpace> spaces, boolean isVersion30AndAbove, File outputFolder) throws IOException, RemoteException, ServiceException, HttpException { String sessionId = login(httpClient); for (ExportSpace space : spaces) { long started = System.currentTimeMillis(); log.info("Starting a Confluence export for space: " + space); log.info("Please wait for the Confluence export process to finish."); log.info("This could take a few minutes ..."); String exportedUrl = export(space, isVersion30AndAbove); long finished = System.currentTimeMillis(); log.info(space.getKey() + " (" + space.getType() + ") -> " + exportedUrl); log.info(took("Confluence export process for " + space.getKey(), finished - started)); String fileName = fileName(exportedUrl, space); log.info("Downloading " + exportedUrl); long downloadStarted = System.currentTimeMillis(); File target = new File(outputFolder, fileName); store(exportedUrl, httpClient, sessionId, target); log.info(took("Downloading " + target.getName(), System.currentTimeMillis() - downloadStarted)); log.info(space.getKey() + " (" + space.getType() + ") -> " + target.getAbsolutePath()); log.info("-----------"); } logout(httpClient); } protected abstract String export(ExportSpace space, boolean isVersion30AndAbove) throws RemoteException, javax.xml.rpc.ServiceException; public void store(String exportedSpaceUrl, DefaultHttpClient client, String sessionId, File targetFile) throws IOException { HttpGet get = new HttpGet(exportedSpaceUrl); get.addHeader("Cookie", "confluence.browse.space.cookie=space-pages; " + "confluence.list.pages.cookie=list-content-tree; " + "JSESSIONID=" + sessionId); get.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); get.addHeader("Accept-Encoding", "gzip, deflate"); InputStream content = null; try { HttpResponse httpResponse = client.execute(get); content = httpResponse.getEntity().getContent(); download(content, targetFile); } finally { IOUtils.closeQuietly(content); } } private void download(InputStream content, File targetFile) throws IOException { if (!targetFile.exists()) { targetFile.setWritable(true); targetFile.getParentFile().mkdirs(); boolean created = targetFile.createNewFile(); if (!created) { throw new IOException("Unable to create file " + targetFile.getAbsolutePath()); } } OutputStream targetStream = null; try { targetStream = new BufferedOutputStream(new FileOutputStream(targetFile), 1024 * 4); IOUtils.copy(content, targetStream); } finally { IOUtils.closeQuietly(targetStream); } } private String fileName(String exportedUrl, ExportSpace space) { if (space.getOutputFileName() == null) { String[] splits = exportedUrl.split("/"); if (splits.length > 0) { return splits[splits.length - 1]; } else { throw new IllegalArgumentException("Unable to split the url " + exportedUrl); } } else { return space.getOutputFileName(); } } protected String login(DefaultHttpClient client) throws IOException, HttpException { HttpPost loginRequest = new HttpPost(confluenceBaseUrl.toExternalForm() + "/login.action"); HttpResponse response = null; try { log.debug("Loggin " + user); loginRequest.setEntity(buildLoginRequestEntity()); response = client.execute(loginRequest); int statusCode = response.getStatusLine().getStatusCode(); log.debug("Login finished with status code " + statusCode); if (response.getStatusLine().getStatusCode() > 400){ throw new HttpException("Unable to login to Confluence: " + IOUtils.toString(response.getEntity().getContent())); } } finally { if (response != null) { IOUtils.closeQuietly(response.getEntity().getContent()); } } String seessionId = extractSessionId(client); log.debug("Got session id " + seessionId); return seessionId; } protected boolean logout(DefaultHttpClient client) throws IOException { HttpGet logoutRequest = new HttpGet(confluenceBaseUrl.toExternalForm()+ "/logout.action"); HttpResponse response = null; try { log.debug("Logging out " + user); response = client.execute(logoutRequest); int statusCode = response.getStatusLine().getStatusCode(); log.debug("Logout finished with status code " + statusCode); if (response.getStatusLine().getStatusCode() > 400){ return false; } } finally { if (response != null) { IOUtils.closeQuietly(response.getEntity().getContent()); } } return true; } /** * Extracts the JSESSIONID cookie from the HttpMethod * * @param client * @return the value of the JSESSIONID cookie */ private String extractSessionId(DefaultHttpClient client) throws HttpException { for (org.apache.http.cookie.Cookie cookie : client.getCookieStore().getCookies()) { if (cookie.getName().equals("JSESSIONID")) { return cookie.getValue(); } } throw new HttpException("No JSESSIONID found in Set-Cookie response header."); } private StringEntity buildLoginRequestEntity() throws UnsupportedEncodingException { StringBuilder content = new StringBuilder(); content.append("os_username=").append(user); content.append("&os_password=").append(password); content.append("&login=Log+In&os_destination="); String contentType = "application/x-www-form-urlencoded"; String encoding = "UTF-8"; return new StringEntity(content.toString(), contentType, encoding); } protected String took(String prefix, long millis){ int seconds = (int) (millis / 1000) % 60 ; int minutes = (int) ((millis / (1000*60)) % 60); int hours = (int) ((millis / (1000*60*60)) % 24); StringBuilder took = new StringBuilder(prefix + " took "); if (hours != 0){ took.append((hours + "h ")); took.append((minutes + "min ")); } else { if (minutes != 0){ took.append((minutes + "min ")); } } took.append(seconds + "seconds"); return took.toString(); } }