package ru.ydn.wicket.wicketorientdb.rest; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.Authenticator; import java.net.CookieHandler; import java.net.HttpURLConnection; import java.net.PasswordAuthentication; import java.net.URL; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.wicket.protocol.http.WebApplication; import org.apache.wicket.request.http.WebRequest; import org.apache.wicket.request.mapper.parameter.PageParameters; import org.apache.wicket.request.resource.AbstractResource; import org.apache.wicket.request.resource.SharedResourceReference; import org.apache.wicket.util.encoding.UrlEncoder; import org.apache.wicket.util.io.IOUtils; import org.apache.wicket.util.string.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.ydn.wicket.wicketorientdb.IOrientDbSettings; import ru.ydn.wicket.wicketorientdb.OrientDbWebApplication; import ru.ydn.wicket.wicketorientdb.OrientDbWebSession; /** * Bridge to OrientDB REST API */ public class OrientDBHttpAPIResource extends AbstractResource { private static final long serialVersionUID = 1L; public static final String MOUNT_PATH = "/orientdb"; public static final String ORIENT_DB_KEY=OrientDBHttpAPIResource.class.getSimpleName(); private static final Logger LOG = LoggerFactory.getLogger(OrientDBHttpAPIResource.class); private static class MultiUserCache implements sun.net.www.protocol.http.AuthCache{ public void put(String pkey, sun.net.www.protocol.http.AuthCacheValue value){ } public sun.net.www.protocol.http.AuthCacheValue get(String pkey, String skey){ return null; } public void remove(String pkey, sun.net.www.protocol.http.AuthCacheValue entry){ } } @Override protected ResourceResponse newResourceResponse(Attributes attributes) { final WebRequest request = (WebRequest) attributes.getRequest(); final HttpServletRequest httpRequest = (HttpServletRequest) request.getContainerRequest(); final PageParameters params = attributes.getParameters(); final ResourceResponse response = new ResourceResponse(); if(response.dataNeedsToBeWritten(attributes)) { String orientDbHttpURL = OrientDbWebApplication.get().getOrientDbSettings().getOrientDBRestApiUrl(); if(orientDbHttpURL!=null) { StringBuilder sb = new StringBuilder(orientDbHttpURL); for(int i=0; i<params.getIndexedCount();i++) { //replace provided database name String segment = i==1?OrientDbWebSession.get().getDatabase().getName():params.get(i).toString(); sb.append(UrlEncoder.PATH_INSTANCE.encode(segment, "UTF8")).append('/'); } if(sb.charAt(sb.length()-1)=='/')sb.setLength(sb.length()-1); String queryString = request.getUrl().getQueryString(); if(!Strings.isEmpty(queryString)) { if(sb.charAt(sb.length()-1)!='?') sb.append('?'); sb.append(queryString); } final String url = sb.toString(); final StringWriter sw = new StringWriter(); final PrintWriter out = new PrintWriter(sw); HttpURLConnection con=null; try { URL orientURL = new URL(url); con = (HttpURLConnection)orientURL.openConnection(); con.setDoInput(true); con.setUseCaches(false); String method = httpRequest.getMethod(); con.setRequestMethod(method); con.setUseCaches(false); if("post".equalsIgnoreCase(method) || "put".equalsIgnoreCase(method)) { int contentLength = httpRequest.getContentLength(); con.setDoOutput(true); String initialContentType = httpRequest.getContentType(); if(initialContentType!=null) con.setRequestProperty("Content-Type", initialContentType); int copied = IOUtils.copy(httpRequest.getInputStream(), con.getOutputStream()); if(contentLength>0 && copied==0) { IOUtils.copy(httpRequest.getInputStream(), con.getOutputStream()); } } IOUtils.copy(con.getInputStream(), out, "UTF-8"); response.setStatusCode(con.getResponseCode()); response.setContentType(con.getContentType()); } catch (IOException e) { LOG.error("Can't communicate with OrientDB REST", e); if(con!=null) { try { response.setError(con.getResponseCode(), con.getResponseMessage()); InputStream errorStream = con.getErrorStream(); if(errorStream!=null) { IOUtils.copy(errorStream, out, "UTF-8"); String errorBody = sw.toString(); LOG.error(errorBody); attributes.getResponse().write(errorBody); } } catch (IOException e1) { LOG.error("Can't response by error", e1); } } } finally { if(con!=null)con.disconnect(); } response.setWriteCallback(new WriteCallback() { @Override public void writeData(Attributes attributes) throws IOException { attributes.getResponse().write(sw.toString()); } }); } else { response.setError(HttpServletResponse.SC_BAD_GATEWAY, "OrientDB REST URL is not specified"); } } return response; } public static void mountOrientDbRestApi(WebApplication app) { mountOrientDbRestApi(new OrientDBHttpAPIResource(), app); } public static void mountOrientDbRestApi(WebApplication app, String... mountPaths) { mountOrientDbRestApi(new OrientDBHttpAPIResource(), app, mountPaths); } /** * Mounts OrientDB REST API Bridge to an app * @param resource {@link OrientDBHttpAPIResource} to mount * @param app {@link WebApplication} to mount to */ public static void mountOrientDbRestApi(OrientDBHttpAPIResource resource, WebApplication app) { mountOrientDbRestApi(resource, app, MOUNT_PATH); } /** * Mounts OrientDB REST API Bridge to an app * @param resource {@link OrientDBHttpAPIResource} to mount * @param app {@link WebApplication} to mount to * @param mountPaths array of paths to mount to */ public static void mountOrientDbRestApi(OrientDBHttpAPIResource resource, WebApplication app, String... mountPaths) { app.getSharedResources().add(ORIENT_DB_KEY, resource); Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { String username; String password; OrientDbWebSession session = OrientDbWebSession.get(); if(session.isSignedIn()) { username = session.getUsername(); password = session.getPassword(); } else { IOrientDbSettings settings = OrientDbWebApplication.get().getOrientDbSettings(); username = settings.getGuestUserName(); password = settings.getGuestPassword(); } return new PasswordAuthentication (username, password.toCharArray()); } }); CookieHandler.setDefault(new PersonalCookieManager()); sun.net.www.protocol.http.AuthCacheValue.setAuthCache(new MultiUserCache()); for (String mountPath : mountPaths) { app.mountResource(mountPath, new SharedResourceReference(ORIENT_DB_KEY)); } } }