1 /*****************************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one                *
3  * or more contributor license agreements.  See the NOTICE file              *
4  * distributed with this work for additional information                     *
5  * regarding copyright ownership.  The ASF licenses this file                *
6  * to you under the Apache License, Version 2.0 (the                         *
7  * "License"); you may not use this file except in compliance                *
8  * with the License.  You may obtain a copy of the License at                *
9  *                                                                           *
10  *     http://www.apache.org/licenses/LICENSE-2.0                            *
11  *                                                                           *
12  * Unless required by applicable law or agreed to in writing,                *
13  * software distributed under the License is distributed on an               *
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY                    *
15  * KIND, either express or implied.  See the License for the                 *
16  * specific language governing permissions and limitations                   *
17  * under the License.                                                        *
18  *                                                                           *
19  *                                                                           *
20  * This file is part of the BeanShell Java Scripting distribution.           *
21  * Documentation and updates may be found at http://www.beanshell.org/       *
22  * Patrick Niemeyer (pat@pat.net)                                            *
23  * Author of Learning Java, O'Reilly & Associates                            *
24  *                                                                           *
25  *****************************************************************************/
26 package bsh;
27 
28 public class Variable implements java.io.Serializable
29 {
30 	static final int DECLARATION=0, ASSIGNMENT=1;
31 	/** A null type means an untyped variable */
32 	String name;
33 	Class type = null;
34 	String typeDescriptor;
35 	Object value;
36 	Modifiers modifiers;
37 	LHS lhs;
38 
Variable( String name, Class type, LHS lhs )39 	Variable( String name, Class type, LHS lhs )
40 	{
41 		this.name = name;
42 		this.lhs = lhs;
43 		this.type = type;
44 	}
45 
Variable( String name, Object value, Modifiers modifiers )46 	Variable( String name, Object value, Modifiers modifiers )
47 		throws UtilEvalError
48 	{
49 		this( name, (Class)null/*type*/, value, modifiers );
50 	}
51 
52 	/**
53 		This constructor is used in class generation.
54 	*/
Variable( String name, String typeDescriptor, Object value, Modifiers modifiers )55 	Variable(
56 		String name, String typeDescriptor, Object value, Modifiers modifiers
57 	)
58 		throws UtilEvalError
59 	{
60 		this( name, (Class)null/*type*/, value, modifiers );
61 		this.typeDescriptor = typeDescriptor;
62 	}
63 
64 	/**
65 		@param value may be null if this
66 	*/
Variable( String name, Class type, Object value, Modifiers modifiers )67 	Variable( String name, Class type, Object value, Modifiers modifiers )
68 		throws UtilEvalError
69 	{
70 
71 		this.name=name;
72 		this.type =	type;
73 		this.modifiers = modifiers;
74 		setValue( value, DECLARATION );
75 	}
76 
77 	/**
78 		Set the value of the typed variable.
79 		@param value should be an object or wrapped bsh Primitive type.
80 		if value is null the appropriate default value will be set for the
81 		type: e.g. false for boolean, zero for integer types.
82 	*/
setValue( Object value, int context )83 	public void setValue( Object value, int context )
84 		throws UtilEvalError
85 	{
86 
87 		// check this.value
88         if (hasModifier("final")) {
89             if (this.value != null) {
90                 throw new UtilEvalError("Final variable '" + getName() + "', can't re-assign.");
91             } else if (value == null && context == DECLARATION) {
92                 return;
93             }
94         }
95 
96         if ( value == null )
97 			value = Primitive.getDefaultValue( type );
98 
99 		if ( lhs != null )
100 		{
101 			lhs.assign( Primitive.unwrap(value), false/*strictjava*/ );
102 			return;
103 		}
104 
105 		// TODO: should add isJavaCastable() test for strictJava
106 		// (as opposed to isJavaAssignable())
107 		if ( type != null )
108 			value = Types.castObject( value, type,
109 				context == DECLARATION ? Types.CAST : Types.ASSIGNMENT
110 			);
111 
112 		this.value= value;
113 	}
114 
115 	/*
116 		Note: UtilEvalError here comes from lhs.getValue().
117 		A Variable can represent an LHS for the case of an imported class or
118 		object field.
119 	*/
getValue()120 	Object getValue()
121 		throws UtilEvalError
122 	{
123 		if ( lhs != null )
124 			return type == null ?
125 				lhs.getValue() : Primitive.wrap( lhs.getValue(), type );
126 
127 		return value;
128 	}
129 
130 	/** A type of null means loosely typed variable */
getType()131 	public Class getType() { return type;	}
132 
getTypeDescriptor()133 	public String getTypeDescriptor() { return typeDescriptor; }
134 
getModifiers()135 	public Modifiers getModifiers() { return modifiers; }
136 
getName()137 	public String getName() { return name; }
138 
hasModifier( String name )139 	public boolean hasModifier( String name ) {
140 		return modifiers != null && modifiers.hasModifier(name);
141 	}
142 
toString()143 	public String toString() {
144 		return "Variable: "+super.toString()+" "+name+", type:"+type
145 			+", value:"+value +", lhs = "+lhs;
146 	}
147 }
148