package com.idega.content.repository.stream.business; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.logging.Level; import org.apache.webdav.lib.WebdavResource; import org.apache.webdav.lib.WebdavResources; import org.directwebremoting.annotations.Param; import org.directwebremoting.annotations.RemoteMethod; import org.directwebremoting.annotations.RemoteProxy; import org.directwebremoting.spring.SpringCreator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import com.idega.builder.bean.AdvancedProperty; import com.idega.builder.business.BuilderLogicWrapper; import com.idega.content.business.ContentConstants; import com.idega.content.business.ContentUtil; import com.idega.content.repository.stream.bean.StreamData; import com.idega.content.repository.stream.bean.StreamResult; import com.idega.content.upload.servlet.ContentFileUploadServlet; import com.idega.core.business.DefaultSpringBean; import com.idega.core.component.bean.RenderedComponent; import com.idega.dwr.business.DWRAnnotationPersistance; import com.idega.idegaweb.IWResourceBundle; import com.idega.presentation.Layer; import com.idega.presentation.Table2; import com.idega.presentation.TableBodyRowGroup; import com.idega.presentation.TableHeaderRowGroup; import com.idega.presentation.TableRow; import com.idega.presentation.text.Heading3; import com.idega.presentation.text.Text; import com.idega.slide.business.IWSlideService; import com.idega.util.ArrayUtil; import com.idega.util.CoreConstants; import com.idega.util.CoreUtil; import com.idega.util.FileUtil; import com.idega.util.IOUtil; import com.idega.util.ListUtil; import com.idega.util.StringUtil; import com.idega.util.URIUtil; @Scope(BeanDefinition.SCOPE_SINGLETON) @Service(RepositoryItemStreamer.BEAN_NAME) @RemoteProxy(creator=SpringCreator.class, creatorParams={ @Param(name="beanName", value=RepositoryItemStreamer.BEAN_NAME), @Param(name="javascript", value=RepositoryItemStreamer.DWR_OBJECT) }, name=RepositoryItemStreamer.DWR_OBJECT) public class RepositoryItemStreamer extends DefaultSpringBean implements DWRAnnotationPersistance { public static final String BEAN_NAME = "repositoryItemStreamer", DWR_OBJECT = "RepositoryItemStreamer"; @Autowired private BuilderLogicWrapper builderLogic; private Map<String, List<StreamResult>> getStreamHistory() { Map<String, List<StreamResult>> history = getCache(BEAN_NAME + "Cache"); return history; } @RemoteMethod public void cleanStreamHistory(String uuid) { if (StringUtil.isEmpty(uuid)) return; getStreamHistory().remove(uuid); } @RemoteMethod public RenderedComponent getStreamResults(String uuid) { if (StringUtil.isEmpty(uuid)) return null; IWResourceBundle iwrb = ContentUtil.getBundle().getResourceBundle(CoreUtil.getIWContext()); Layer results = new Layer(); results.setStyleClass(BEAN_NAME + "Results"); List<StreamResult> streamResults = getStreamHistory().get(uuid); if (ListUtil.isEmpty(streamResults)) { results.add(new Heading3(iwrb.getLocalizedString("no_information_about_streaming", "There is no information about the streaming results yet"))); } else { streamResults = new ArrayList<StreamResult>(streamResults); String success = iwrb.getLocalizedString("succeeded", "Succeeded"); String failure = iwrb.getLocalizedString("failed", "Failed"); String seconds = iwrb.getLocalizedString("seconds", "seconds"); Table2 table = new Table2(); results.add(table); TableHeaderRowGroup header = table.createHeaderRowGroup(); TableRow row = header.createRow(); row.createCell().add(new Text(iwrb.getLocalizedString("file_name", "File name"))); row.createCell().add(new Text(iwrb.getLocalizedString("size", "Size"))); row.createCell().add(new Text(iwrb.getLocalizedString("took_time", "Streaming time"))); row.createCell().add(new Text(iwrb.getLocalizedString("status", "Status"))); TableBodyRowGroup body = table.createBodyRowGroup(); for (StreamResult result: streamResults) { row = body.createRow(); row.createCell().add(new Text(result.getName())); row.createCell().add(new Text(FileUtil.getHumanReadableSize(result.getSize()))); row.createCell().add(new Text(String.valueOf(result.getTime() / 1000000000).concat(CoreConstants.SPACE).concat(seconds))); row.createCell().add(new Text(result.isSuccess() ? success : failure)); } } return builderLogic.getBuilderService(getApplication().getIWApplicationContext()).getRenderedComponent(results, null); } @RemoteMethod public AdvancedProperty streamToServer(String server, String repositoryItem, String toFolder, boolean reCreateStructure, String uuid) { AdvancedProperty result = new AdvancedProperty(Boolean.FALSE.toString()); IWResourceBundle iwrb = ContentUtil.getBundle().getResourceBundle(CoreUtil.getIWContext()); if ((StringUtil.isEmpty(server) || "http://".equals(server) || "https://".equals(server)) || StringUtil.isEmpty(repositoryItem) || StringUtil.isEmpty(toFolder)) { String message = "Server, repository item or destination folder are not defined"; getLogger().warning(message); result.setValue(iwrb.getLocalizedString("error_streaming_incorrect_data", message)); return result; } String originalServer = server; if (!server.endsWith(CoreConstants.SLASH)) server = server.concat(CoreConstants.SLASH); if (toFolder.indexOf(CoreConstants.DOT) != -1) // File toFolder = toFolder.substring(0, toFolder.lastIndexOf(CoreConstants.SLASH)); if (!toFolder.endsWith(CoreConstants.SLASH)) toFolder = toFolder.concat(CoreConstants.SLASH); server = server.concat("servlet/ContentFileUploadServlet"); URIUtil uri = new URIUtil(server); uri.setParameter(ContentConstants.UPLOADER_PATH, toFolder); uri.setParameter(ContentFileUploadServlet.PARAMETER_BINARY_STREAM, Boolean.TRUE.toString()); String url = uri.getUri(); try { IWSlideService repository = getServiceInstance(IWSlideService.class); WebdavResource resource = repository.getWebdavResourceAuthenticatedAsRoot(repositoryItem); if (writeItems(resource, url, toFolder, reCreateStructure, uuid)) { result.setId(Boolean.TRUE.toString()); result.setValue(iwrb.getLocalizedString("success_streaming", "Data were succussefully streamed to").concat(CoreConstants.SPACE).concat(originalServer)); } else result.setValue(iwrb.getLocalizedString("error_streaming", "Sorry, some error occurred while streaming data to").concat(CoreConstants.SPACE) .concat(originalServer)); } catch (Exception e) { getLogger().log(Level.WARNING, "Error streaming " + repositoryItem + " to server " + uri.getUri(), e); } return result; } private boolean writeItems(WebdavResource resource, String uri, String toFolder, boolean reCreateStructure, String uuid) throws IOException { if (resource == null || !resource.exists()) return false; if (resource.isCollection()) { WebdavResources resources = resource.getChildResources(); if (resources == null) return false; WebdavResource[] childResources = resources.listResources(); if (ArrayUtil.isEmpty(childResources)) return true; for (WebdavResource childResource: childResources) { if (!writeItems(childResource, uri, toFolder, reCreateStructure, uuid)) return false; } } else { return writeItem(resource, uri, toFolder, reCreateStructure, uuid); } return true; } private boolean writeItem(WebdavResource file, String uri, String toFolder, boolean reCreateStructure, String uuid) throws IOException { long start = System.nanoTime(); URL url = new URL(uri); URLConnection conn = url.openConnection(); if (conn instanceof HttpURLConnection) { HttpURLConnection connection = (HttpURLConnection) conn; String destination = toFolder; if (reCreateStructure) { destination = file.getPath(); if (destination.startsWith(CoreConstants.WEBDAV_SERVLET_URI)) destination = destination.replaceFirst(CoreConstants.WEBDAV_SERVLET_URI, CoreConstants.EMPTY); if (destination.indexOf(CoreConstants.DOT) != -1) destination = destination.substring(0, destination.lastIndexOf(CoreConstants.SLASH)); if (!destination.endsWith(CoreConstants.SLASH)) destination = destination.concat(CoreConstants.SLASH); } StreamData data = new StreamData(file.getDisplayName(), destination, uuid, file.getMethodData()); byte[] objectData = IOUtil.getBytesFromObject(data); connection.setRequestMethod("POST"); connection.setFixedLengthStreamingMode(objectData.length); connection.setRequestProperty("Content-Type", "text/plain;charset=".concat(CoreConstants.ENCODING_UTF8)); connection.setRequestProperty("Accept", "text/plain"); connection.setRequestProperty("Content-Length", String.valueOf(objectData.length)); connection.setDoOutput(true); connection.connect(); OutputStream os = connection.getOutputStream(); os.write(objectData); os.flush(); os.close(); StreamResult result = IOUtil.getObjectFromInputStream(connection.getInputStream()); if (result == null) return false; long end = System.nanoTime(); result.setTime(end - start); Map<String, List<StreamResult>> history = getStreamHistory(); List<StreamResult> results = history.get(uuid); if (results == null) { results = new ArrayList<StreamResult>(); history.put(uuid, results); } results.add(result); return result.isSuccess(); } else { getLogger().warning("Can not stream using connection " + conn + ". It is required to open " + HttpURLConnection.class.getName()); } return false; } }