001: /*
002: * Copyright (c) 2003 The Visigoth Software Society. All rights
003: * reserved.
004: *
005: * Redistribution and use in source and binary forms, with or without
006: * modification, are permitted provided that the following conditions
007: * are met:
008: *
009: * 1. Redistributions of source code must retain the above copyright
010: * notice, this list of conditions and the following disclaimer.
011: *
012: * 2. Redistributions in binary form must reproduce the above copyright
013: * notice, this list of conditions and the following disclaimer in
014: * the documentation and/or other materials provided with the
015: * distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowledgement:
019: * "This product includes software developed by the
020: * Visigoth Software Society (http://www.visigoths.org/)."
021: * Alternately, this acknowledgement may appear in the software itself,
022: * if and wherever such third-party acknowledgements normally appear.
023: *
024: * 4. Neither the name "FreeMarker", "Visigoth", nor any of the names of the
025: * project contributors may be used to endorse or promote products derived
026: * from this software without prior written permission. For written
027: * permission, please contact visigoths@visigoths.org.
028: *
029: * 5. Products derived from this software may not be called "FreeMarker" or "Visigoth"
030: * nor may "FreeMarker" or "Visigoth" appear in their names
031: * without prior written permission of the Visigoth Software Society.
032: *
033: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
034: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
035: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
036: * DISCLAIMED. IN NO EVENT SHALL THE VISIGOTH SOFTWARE SOCIETY OR
037: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
038: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
039: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
040: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
041: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
042: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
043: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
044: * SUCH DAMAGE.
045: * ====================================================================
046: *
047: * This software consists of voluntary contributions made by many
048: * individuals on behalf of the Visigoth Software Society. For more
049: * information on the Visigoth Software Society, please see
050: * http://www.visigoths.org/
051: */
052:
053: package freemarker.debug;
054:
055: import java.io.IOException;
056: import java.io.ObjectInputStream;
057: import java.io.ObjectOutputStream;
058: import java.net.InetAddress;
059: import java.net.Socket;
060: import java.rmi.RemoteException;
061: import java.rmi.server.RemoteObject;
062: import java.security.MessageDigest;
063: import java.util.Collection;
064: import java.util.List;
065:
066: import freemarker.debug.impl.RmiDebuggerListenerImpl;
067: import freemarker.template.utility.UndeclaredThrowableException;
068:
069: /**
070: * A utility class that allows you to connect to the FreeMarker debugger service
071: * running on a specific host and port.
072: * @author Attila Szegedi
073: * @version $Id: DebuggerClient.java,v 1.3.2.1 2006/11/27 07:54:19 szegedia Exp $
074: */
075: public class DebuggerClient {
076: private DebuggerClient() {
077: }
078:
079: /**
080: * Connects to the FreeMarker debugger service running on a specific host
081: * and port. The Java VM to which the connection is made must have defined
082: * the system property <tt>freemarker.debug.password</tt> in order to enable
083: * the debugger service. Additionally, the <tt>freemarker.debug.port</tt>
084: * system property can be set to specify the port where the debugger service
085: * is listening. When not specified, it defaults to
086: * {@link Debugger#DEFAULT_PORT}.
087: * @param host the host address of the machine where the debugger service is
088: * running.
089: * @param port the port of the debugger service
090: * @param password the password required to connect to the debugger service
091: * @return Debugger a debugger object. null is returned in case incorrect
092: * password was supplied.
093: * @throws IOException if an exception occurs.
094: */
095: public static Debugger getDebugger(InetAddress host, int port,
096: String password) throws IOException {
097: try {
098: Socket s = new Socket(host, port);
099: try {
100: ObjectOutputStream out = new ObjectOutputStream(s
101: .getOutputStream());
102: ObjectInputStream in = new ObjectInputStream(s
103: .getInputStream());
104: int protocolVersion = in.readInt();
105: if (protocolVersion > 220) {
106: throw new IOException(
107: "Incompatible protocol version "
108: + protocolVersion
109: + ". At most 220 was expected.");
110: }
111: byte[] challenge = (byte[]) in.readObject();
112: MessageDigest md = MessageDigest.getInstance("SHA");
113: md.update(password.getBytes("UTF-8"));
114: md.update(challenge);
115: out.writeObject(md.digest());
116: return new LocalDebuggerProxy((Debugger) in
117: .readObject());
118: //return (Debugger)in.readObject();
119: } finally {
120: s.close();
121: }
122: } catch (IOException e) {
123: throw e;
124: } catch (Exception e) {
125: throw new UndeclaredThrowableException(e);
126: }
127: }
128:
129: private static class LocalDebuggerProxy implements Debugger {
130: private final Debugger remoteDebugger;
131:
132: LocalDebuggerProxy(Debugger remoteDebugger) {
133: this .remoteDebugger = remoteDebugger;
134: }
135:
136: public void addBreakpoint(Breakpoint breakpoint)
137: throws RemoteException {
138: remoteDebugger.addBreakpoint(breakpoint);
139: }
140:
141: public Object addDebuggerListener(DebuggerListener listener)
142: throws RemoteException {
143: if (listener instanceof RemoteObject) {
144: return remoteDebugger.addDebuggerListener(listener);
145: } else {
146: RmiDebuggerListenerImpl remotableListener = new RmiDebuggerListenerImpl(
147: listener);
148: return remoteDebugger
149: .addDebuggerListener(remotableListener);
150: }
151: }
152:
153: public List getBreakpoints() throws RemoteException {
154: return remoteDebugger.getBreakpoints();
155: }
156:
157: public List getBreakpoints(String templateName)
158: throws RemoteException {
159: return remoteDebugger.getBreakpoints(templateName);
160: }
161:
162: public Collection getSuspendedEnvironments()
163: throws RemoteException {
164: return remoteDebugger.getSuspendedEnvironments();
165: }
166:
167: public void removeBreakpoint(Breakpoint breakpoint)
168: throws RemoteException {
169: remoteDebugger.removeBreakpoint(breakpoint);
170: }
171:
172: public void removeBreakpoints(String templateName)
173: throws RemoteException {
174: remoteDebugger.removeBreakpoints(templateName);
175: }
176:
177: public void removeBreakpoints() throws RemoteException {
178: remoteDebugger.removeBreakpoints();
179: }
180:
181: public void removeDebuggerListener(Object id)
182: throws RemoteException {
183: remoteDebugger.removeDebuggerListener(id);
184: }
185: }
186: }
|