| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| #include "open/vm_class_manipulation.h" |
| #include "open/vm_class_loading.h" |
| |
| #include "verifier.h" |
| #include "context_base.h" |
| |
| /** |
| * Checkes constraint for given class and loads classes if it's needed. |
| */ |
| vf_Result vf_force_check_constraint(Class_Handle klass, |
| vf_TypeConstraint* constraint) // class constraint |
| { |
| // get target class |
| Class_Handle target = vf_resolve_class( klass, constraint->target, true ); |
| if( !target ) { |
| return VF_ErrorLoadClass; |
| } |
| |
| //no need to load the source |
| if(class_is_interface(target)){ |
| return VF_OK; |
| } |
| |
| |
| // get stack reference class |
| Class_Handle source = vf_resolve_class( klass, constraint->source, true ); |
| if( !source ) { |
| return VF_ErrorLoadClass; |
| } |
| |
| // check restriction |
| if( !vf_is_extending( source, target ) ) { |
| return VF_ErrorIncompatibleArgument; |
| } |
| return VF_OK; |
| } // vf_force_check_constraint |
| |
| |
| /** |
| * Returns true if 'from' is (not necessarily directly) extending 'to'. |
| */ |
| int vf_is_extending(Class_Handle from, Class_Handle to) { |
| while (from) { |
| if( from == to ) return true; |
| from = class_get_super_class(from); |
| } |
| return false; |
| } |
| |
| /** |
| * Receives class by given class name, loads it if it's needed. |
| */ |
| Class_Handle |
| vf_resolve_class( Class_Handle k_class, // current class |
| const char *name, // resolved class name |
| bool need_load) // load flag |
| { |
| Class_Handle result; |
| |
| // get class loader |
| Class_Loader_Handle class_loader = class_get_class_loader( k_class ); |
| |
| result = need_load ? |
| class_loader_load_class( class_loader, name ) |
| : class_loader_lookup_class( class_loader, name ); |
| |
| //we assume that this pre-defined constant is not a valid class-handler |
| assert(CLASS_NOT_LOADED != result); |
| |
| return result; |
| } // vf_resolve_class |